<template>
  <div class="page-outer page-body">
    <div class="page-inner">
      <!-- ============================= 搜索区 ============================= -->
      <div class="card search-card">
        <div class="search-row">
          <!-- 左：输入 + 查询按钮 -->
          <div class="search-left">
            <a-input v-model:value="searchKeyword" class="search-input" placeholder="输入【索引名称】查询" allow-clear
              @blur="onSearchBlur" @keyup.enter="onSearchClick">
              <template #prefix><icon-search-outlined /></template>
            </a-input>

            <!-- 查询按钮 -->
            <a-button type="primary" class="search-btn" :loading="loading && searchLoadingLock" @click="onSearchClick">
              <icon-search-outlined style="margin-right: 4px" /> 查询
            </a-button>
          </div>

          <!-- 右：操作按钮 -->
          <div class="actions">
            <a-button class="btn-soft" :loading="loading" @click="onSync">
              <icon-sync-outlined style="margin-right: 4px" /> 同步
            </a-button>
            <a-button class="btn-soft" @click="onReload">
              <icon-reload-outlined style="margin-right: 4px" /> 刷新
            </a-button>
            <a-button type="primary" @click="onAddIndex">+ 新增索引</a-button>
          </div>
        </div>
      </div>

      <!-- ============================= 列表区 ============================= -->
      <div class="card table-card list-card">
        <div class="table-main">
          <a-table :columns="columns" :data-source="dataSource" row-key="index_id" :loading="loading"
            :pagination="false" :row-selection="rowSelection" class="custom-table" size="small" tableLayout="fixed"
            :scroll="tableScroll" :customRow="customRow" :rowClassName="() => 'clickable-row'">
            <template #bodyCell="{ column, record, index }">
              <!-- 自增序号 -->
              <template v-if="column.dataIndex === '__serial'">
                {{ (pagination.current - 1) * pagination.pageSize + index + 1 }}
              </template>

              <!-- 索引名称（点击跳详情） -->
              <span v-else-if="column.dataIndex === 'index_name'">
                <a href="javascript:;" class="link name-black" @click="gotoDetail(record)">{{ record.index_name || "—"
                }}</a>
              </span>

              <!-- 上次更新时间 -->
              <span v-else-if="column.dataIndex === 'last_update_time'">
                {{ formatTime(getLastUpdateTime(record)) }}
              </span>

              <!-- 权限 -->
              <span v-else-if="column.dataIndex === 'permission'">
                {{ formatPermission(record.permission) }}
              </span>

              <!-- 更新策略 -->
              <span v-else-if="column.dataIndex === 'datasync_strategy'">
                {{ record.datasync_strategy ?? "—" }}
              </span>

              <!-- 更新状态 -->
              <span v-else-if="column.dataIndex === 'datasync_message'">
                <span :class="['status-tag', getStatusInfoFromMsg(record.datasync_message).cls]">
                  {{ getStatusInfoFromMsg(record.datasync_message).text }}
                </span>
              </span>

              <!-- 数据模型 -->
              <span v-else-if="column.dataIndex === 'data_model'">
                {{ getIndexModel(record) ?? "—" }}
              </span>

              <!-- 文档量 -->
              <span v-else-if="column.dataIndex === 'doc_count'">
                {{ formatDocCount(record) }}
              </span>

              <!-- 操作列 -->
              <template v-else-if="column.dataIndex === 'action'">
                <div class="action-cell">
                  <span class="action-link" @click="handleEdit(record)">编辑</span>
                  <span class="sep">|</span>
                  <span class="action-link" @click="handleLog(record)">日志</span>
                  <span class="sep">|</span>
                  <span class="action-link" @click="handleRefresh(record)">刷新</span>
                  <span class="sep">|</span>
                  <span class="action-link" v-if="Number(record.datasync_state) !== 3"
                    @click="handleToggleState(record)">
                    {{ getToggleText(record.datasync_state) }}
                  </span>
                  <span class="sep" v-if="Number(record.datasync_state) !== 3">|</span>
                  <span class="action-link" @click="handleSearchAPI(record)">搜索接口</span>
                </div>
              </template>

              <!-- 兜底 -->
              <span v-else>{{ record[column.dataIndex] ?? "—" }}</span>
            </template>
          </a-table>
        </div>

        <!-- ============================= 分页 ============================= -->
        <div class="table-footer">
          <div class="footer-left">
            <span v-if="dataSource.length">已选择 {{ selectedRowKeys.length }} 条，共 {{ total }} 条</span>
          </div>
          <div class="footer-right">
            <a-pagination v-model:current="pagination.current" v-model:page-size="pagination.pageSize" :total="total"
              :show-size-changer="true" :page-size-options="['10', '20', '50', '100']" show-quick-jumper show-less-items
              @change="handlePageChange" @showSizeChange="handlePageSizeChange" />
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, computed } from "vue";
import Http from "@/api";
import { useRouter } from "vue-router";
import {
  SearchOutlined as IconSearchOutlined,
  SyncOutlined as IconSyncOutlined,
  ReloadOutlined as IconReloadOutlined,
} from "@ant-design/icons-vue";
import { Table, message } from "ant-design-vue";
import { debounce } from "lodash-es";
import dayjs from "dayjs";

const router = useRouter();

/* ----------------------------- 表格列定义 ----------------------------- */
const columns = [
  // { title: "ID", dataIndex: "__serial", align: "center", width: 90, ellipsis: true, fixed: "left" },
  { title: "索引名称", dataIndex: "index_name", align: "center", width: 220, ellipsis: true, fixed: "left" },
  { title: "索引类型", dataIndex: "index_type", align: "center", width: 120, ellipsis: true },
  { title: "数据模型", dataIndex: "data_model", align: "center", width: 140, ellipsis: true },
  { title: "权限", dataIndex: "permission", align: "center", width: 100, ellipsis: true },
  { title: "上次更新时间", dataIndex: "last_update_time", align: "center", width: 180, ellipsis: true },
  { title: "更新策略", dataIndex: "datasync_strategy", align: "center", width: 140, ellipsis: true },
  { title: "更新状态", dataIndex: "datasync_message", align: "center", width: 140, ellipsis: true },
  { title: "文档量", dataIndex: "doc_count", align: "center", width: 120, ellipsis: true },
  { title: "操作", dataIndex: "action", align: "center", width: 260, fixed: "right", className: "col-action" },
];

/* ----------------------------- 工具函数 ----------------------------- */
const formatTime = (val: string | number | null | undefined) =>
  !val ? "—" : dayjs(val).format("YYYY-MM-DD HH:mm:ss");
const getLastUpdateTime = (r: any) => r?.last_update_time ?? r?.update_time ?? null;
const formatPermission = (val: any) => {
  if (val === 1 || val === "1" || val === "public" || val === "公开") return "公开";
  if (val === 0 || val === "0" || val === "private" || val === "私密") return "私密";
  return val ?? "—";
};
const clamp = (n: number, min = 0, max = 100) => Math.max(min, Math.min(max, n));
function parsePercentFromText(msg: string): number | undefined {
  if (!msg) return undefined;
  const m = msg.match(/(\d{1,3})\s*%?/);
  if (!m) return undefined;
  const v = Number(m[1]);
  if (!Number.isFinite(v)) return undefined;
  return clamp(Math.round(v));
}
function getStatusInfoFromMsg(raw: any) {
  const txt = String(raw ?? "").trim();
  const p = parsePercentFromText(txt);
  const isFail = /失败|fail|error/i.test(txt);
  const isSuccess = /完成|成功|done|success/i.test(txt) || (typeof p === "number" && p >= 100);
  const isProgress = /进行中|progress/i.test(txt) || (typeof p === "number" && p < 100 && !isFail);
  if (isFail) return { text: p === undefined ? "失败" : `失败${p}%`, cls: "is-fail" };
  if (isSuccess) return { text: "完成100%", cls: "is-success" };
  if (isProgress) return { text: `进行中${p ?? 0}%`, cls: "is-progress" };
  return { text: txt || "—", cls: "is-default" };
}
const formatDocCount = (r: any) => {
  const v = r?.doc_count ?? r?.document_count;
  const num = Number(v);
  if (typeof v === "number" && Number.isFinite(v)) return v.toLocaleString();
  if (typeof v === "string" && v.trim() !== "" && Number.isFinite(num)) return num.toLocaleString();
  return v ?? "—";
};
const getIndexModel = (r: any) => r?.data_model ?? r?.index_model ?? r?.model ?? r?.dataModel ?? null;

/* ----------------------------- 计算属性 / 状态 ----------------------------- */
const loading = ref(false);
const dataSource = ref<any[]>([]);
const total = ref(0);
const searchKeyword = ref("");
const pagination = ref({ current: 1, pageSize: 10 });

/** 查询按钮轻量锁 */
const searchLoadingLock = ref(false);

/** 表格横向滚动宽度 */
const tableScroll = computed(() => {
  const x = columns.reduce((s, c) => s + (Number(c.width) || 120), 0);
  return { x };
});

/* ----------------------------- 搜索相关 ----------------------------- */
const doSearch = debounce(() => {
  pagination.value.current = 1;
  fetchData();
}, 300);

const onSearchBlur = () => {
  if (!searchKeyword.value.trim()) searchKeyword.value = "";
  doSearch();
};

const onSearchClick = () => {
  try {
    searchLoadingLock.value = true;
    pagination.value.current = 1;
    fetchData();
  } finally {
    setTimeout(() => (searchLoadingLock.value = false), 150);
  }
};

/* ----------------------------- 勾选 ----------------------------- */
const selectedRowKeys = ref<(string | number)[]>([]);
const rowSelection = computed(() => ({
  selectedRowKeys: selectedRowKeys.value,
  onChange: (keys: (string | number)[]) => (selectedRowKeys.value = keys),
  selections: [Table.SELECTION_ALL],
  preserveSelectedRowKeys: true,
  getCheckboxProps: (record: any) => ({
    disabled: Number(record?.datasync_state) === 1 || Number(record?.datasync_state) === 3,
  }),
}));

/* ----------------------------- 列表行跳详情 ----------------------------- */
const gotoDetail = (r: any) => {
  router.push({ path: "/management_details", query: { index_id: String(r?.index_id ?? "") } });
};
function customRow(record: any) {
  return {
    onClick: (e: MouseEvent) => {
      const t = e.target as HTMLElement;
      if (
        t.closest('.ant-table-selection-column') ||
        t.closest('.action-cell') ||
        t.closest('.ant-checkbox') ||
        t.closest('button') ||
        t.closest('a')
      ) return;
      gotoDetail(record);
    }
  };
}

/* ----------------------------- 数据获取 ----------------------------- */
const fetchData = async () => {
  const params: Record<string, any> = {
    page: pagination.value.current,
    page_size: pagination.value.pageSize,
    index_name: searchKeyword.value.trim() || "",
    fields:
      "index_id,index_name,index_type,permission,last_update_time,datasync_strategy,datasync_message,doc_count,datasync_state,data_model",
    with_data_model: 1,
  };
  try {
    loading.value = true;
    const res = await Http.getPageList(params);
    const raw = Array.isArray(res?.data) ? res.data : [];
    dataSource.value = raw.map((r: any) => ({
      ...r,
      data_model: r?.data_model ?? r?.index_model ?? r?.model ?? r?.dataModel ?? r?.index_model_name,
    }));
    total.value = Number(res?.total ?? dataSource.value.length);
  } catch (e) {
    console.error("获取索引列表失败：", e);
  } finally {
    loading.value = false;
  }
};

/* ----------------------------- 顶部按钮行为 ----------------------------- */
const onReload = () => {
  pagination.value.current = 1;
  selectedRowKeys.value = [];
  fetchData();
};
const onAddIndex = () => router.push("/management-add");
const onSync = async () => {
  const ids = selectedRowKeys.value.map((k) => Number(k)).filter((n) => Number.isFinite(n) && n > 0);
  if (!ids.length) {
    message.warning("请先在左侧勾选需要同步的索引");
    return;
  }
  try {
    loading.value = true;
    await Http.dataSync({ index_ids: ids });
    message.success("勾选项已全部同步");
    selectedRowKeys.value = [];
    await fetchData();
  } catch (e: any) {
    message.error(e?.message || "同步失败");
  } finally {
    loading.value = false;
  }
};

/* ----------------------------- 行内操作 ----------------------------- */
const onAddIndexOld = () => router.push("/management-add");
const handleEdit = (r: any) => {
  router.push({ path: "/management-info", query: { index_id: String(r.index_id ?? ""), mode: "edit" } });
};
const handleLog = (r: any) => {
  router.push({ path: "/log", query: { index_id: String(r.index_id ?? "") } });
};
const handleRefresh = async (r: any) => {
  const id = Number(r?.index_id);
  if (!Number.isFinite(id) || id <= 0) {
    message.error("无法获取有效的 index_id");
    return;
  }
  try {
    loading.value = true;
    await (Http as any).getRefreshOne({ indexId: id });
    message.success("已触发刷新");
    await fetchData();
  } catch (e: any) {
    message.error(e?.message || "刷新失败");
  } finally {
    loading.value = false;
  }
};
const handleSearchAPI = (r: any) => {
  console.log("搜索接口");
};
const getToggleText = (state: any) => (Number(state) === 1 ? "暂停" : "启动");
const handleToggleState = async (r: any) => {
  const id = Number(r?.index_id);
  if (!Number.isFinite(id) || id <= 0) {
    message.error("无法获取有效的 index_id");
    return;
  }
  const current = Number(r?.datasync_state) === 1 ? 1 : 0;
  try {
    loading.value = true;
    if (current === 1) {
      await (Http as any).stopSync({ index_ids: [id] });
      message.success("已暂停");
      const idx = dataSource.value.findIndex((x) => Number(x.index_id) === id);
      if (idx > -1) dataSource.value[idx].datasync_state = 0;
    } else {
      await Http.dataSync({ index_ids: [id] });
      message.success("已启动");
      const idx = dataSource.value.findIndex((x) => Number(x.index_id) === id);
      if (idx > -1) dataSource.value[idx].datasync_state = 1;
    }
    await fetchData();
  } catch (e: any) {
    message.error(e?.message || "操作失败");
  } finally {
    loading.value = false;
  }
};

/* ----------------------------- 分页 ----------------------------- */
const handlePageChange = (p: number) => {
  pagination.value.current = p;
  fetchData();
};
const handlePageSizeChange = (_: number, size: number) => {
  pagination.value.pageSize = size;
  pagination.value.current = 1;
  fetchData();
};

/* ----------------------------- 初始化拉取 ----------------------------- */
onMounted(fetchData);
</script>

<style lang="less" scoped>
/* ============================= 变量 ============================= */
@card-radius: 12px;
@card-border: #f0f0f0;
@page-bg: #f5f6f8;

/* ============================= 页面布局 ============================= */
.page-outer {
  width: 100%;
  min-height: 100vh;
  background: @page-bg;
}

.page-inner {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-height: 100vh;
  padding: 10px;
}

/* 卡片 */
.card {
  background: #fff;
  border: 1px solid @card-border;
  border-radius: @card-radius;
  padding: 12px 16px;
}

/* 列表容器 */
.list-card {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
  border-radius: 8px;
}

.table-main {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
}

/* ============================= 搜索行 ============================= */
.search-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  column-gap: 10px;
}

.search-left {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

.search-input {
  width: 340px;

  :deep(.ant-input-affix-wrapper) {
    padding: 5px 10px;
    border-radius: 8px;
    border: 1px solid #d9d9d9;
    background: #fff;
  }

  :deep(.ant-input) {
    font-size: 14px;
    line-height: 18px;
    color: #1f1f1f;
    font-weight: 400;
  }

  :deep(.ant-input::placeholder) {
    font-size: 14px;
  }
}

.search-btn {
  height: 34px;
  padding: 0 14px;
}

/* 顶部按钮 */
.actions {
  display: flex;
  align-items: center;
  gap: 10px;
}

.actions :deep(.ant-btn) {
  height: 32px;
  border-radius: 6px;
  font-size: 14px;
}

.btn-soft {
  background: #fff;
  border: 1px solid #d9d9d9;
  color: #1f1f1f;
}

/* ============================= 表格样式 ============================= */
.custom-table {
  :deep(.ant-table) {
    font-size: 14px;
    color: #1f1f1f;
  }

  :deep(.ant-table-thead > tr > th) {
    height: 40px !important;
    text-align: center;
    background: #f7f8fa;
    font-weight: 600;
    color: #1f1f1f;
  }

  :deep(.ant-table-tbody > tr > td) {
    height: 40px !important;
    padding: 0 8px !important;
    vertical-align: middle;
    font-weight: 400;
    color: #1f1f1f;
  }

  :deep(.ant-table-tbody > tr.ant-table-measure-row) {
    display: none !important;
  }

  /* 行可点击的光标反馈 */
  :deep(.clickable-row) {
    cursor: pointer;
  }
}

/* 索引名称黑色 */
.link.name-black {
  color: #1f1f1f;
  text-decoration: none;
}

/* 操作列 */
.action-cell {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: center;
  line-height: 1.2;
}

.action-link {
  color: #1677ff;
  cursor: pointer;
}

.sep {
  color: #e5e6eb;
}

/* 状态标签 */
.status-tag {
  display: inline-block;
  padding: 0 8px;
  height: 22px;
  line-height: 22px;
  border-radius: 12px;
  font-size: 12px;
  border: 1px solid transparent;
}

.is-progress {
  color: #1677ff;
  background: #e6f4ff;
  border-color: #91caff;
}

.is-fail {
  color: #ff4d4f;
  background: #fff1f0;
  border-color: #ffa39e;
}

.is-success {
  color: #52c41a;
  background: #f6ffed;
  border-color: #b7eb8f;
}

.is-default {
  color: #606266;
  background: #f5f5f5;
  border-color: #e8e8e8;
}

/* ============================= 分页 ============================= */
.table-footer {
  flex: 0 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 8px;
  margin-top: 45px;
  border-top: 1px solid @card-border;
  position: sticky;
  bottom: calc(env(safe-area-inset-bottom, 0px) + 30px);
  background: #fff;
  z-index: 2000;
  padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
  left: 0;
  right: 0;
  width: 100%;
}

/* ============================= 响应式 ============================= */
@media (max-width: 991px) {
  .search-row {
    flex-direction: column;
    align-items: stretch;
    row-gap: 10px;
  }

  .search-input {
    width: 100%;
  }
}

@media (max-width: 767px) {
  .actions :deep(.ant-btn) {
    height: 28px;
    padding: 0 8px;
    font-size: 12px;
  }

  .custom-table :deep(.ant-table) {
    font-size: 13px;
  }
}
</style>
